<?php
/**
 * ErrorHook
 * 
 * @author Alexey Strelnikoff <zog@zoggi.net>
 */

namespace Zoggi\ErrorHook;

/**
 * Класс для описания одной конкретной ошибки.
 */
class ErrorUnit {

	public $errno;
	public $errstr;
	public $file;
	public $line;
	public $backtrace;

	/**
	 * Возвращет одну конкрeтную ошибку 
	 * 
	 * @param int $errno - код ошибки
	 * @param string $errstr - сообщение об ошибке
	 * @param string $file - файл
	 * @param int $line - строка
	 * 
	 * @return ErrorUnit
	 */
	public function __construct( $errno, $errstr, $file, $line ) {
		$this->errno = $errno;
		$this->errstr = $errstr;
		$this->file = $file;
		$this->line = $line;
		$this->backtrace = ErrorUnit::getTrace();
	}

	/**
	 * Возвращает ошибку в виде строки в формате $format
	 * 
	 * @param string $format
	 * 
	 * @return string
	 */
	public function toString( $format = "%errname%: %errstr% in %file% as %line%\n%trace%" ) {

		$errors = array(
			1 => 'E_ERROR', 2 => 'E_WARNING', 8 => 'E_NOTICE',
			256 => 'E_USER_ERROR', 512 => 'E_USER_WARNING', 1024 => 'E_USER_NOTICE',
			2048 => 'E_STRICT', 4096 => 'E_RECOVERABLE_ERROR', 8192 => 'E_DEPRECATED',
		);

		$message = strtr($format, array(
			'%errname%' => ( empty($errors[$this->errno]) ? "E_UNKNOWN (" . $this->errno . ")" : $errors[$this->errno] ),
			'%errno%' => $this->errno,
			'%errstr%' => $this->errstr,
			'%file%' => $this->file,
			'%line%' => $this->line,
			));

		$trace = array();
		foreach ( $this->backtrace as $k => $v ) {
			$trace[] = sprintf(
				"\t%s->%s in %s at %s", $v['class'], $v['function'], $v['file'], $v['line']
			);
		}

		$message = strtr($message, array(
			'%trace%' => join("\n", $trace)
			));

		return $message;
	}

	/**
	 * Возвращает ошибку в виде строки
	 * 
	 * @return string
	 */
	public function __toString() {
		return $this->toString();
	}

	/**
	 * Возвращает ошибку в html формате
	 *
	 * @return string
	 */
	public function toHtml() {

		return $this->toString("<pre><b>%errname%: %errstr%</b> in %file% as %line%<br/>%trace%</pre>");
	}

	/**
	 * Возвращает backtrace последней ошибки
	 * 
	 * Возвращает array( array(file,line,class,function) )
	 *
	 * @return array
	 */
	public static function getTrace() {

		$trace = array();
		$backtrace = debug_backtrace();
		// выкидываем первые три записи из backtrace
		$backtrace = array_splice($backtrace, 3);

		foreach ( $backtrace as $k => $v ) {
			$trace[] = array(
				'file' => empty($v['file']) ? '' : $v['file'],
				'line' => empty($v['line']) ? '' : $v['line'],
				'class' => empty($v['class']) ? '' : $v['class'],
				'function' => empty($v['function']) ? '' : $v['function'],
			);
		}
		return $trace;
	}

	/**
	 * Возвращает попадает ли ошибка в $errorLevel
	 * 
	 * @param int $errorLevel Номер ошибки
	 * @return boolean
	 */
	public function checkLevel( $errorLevel ) {

		return $this->errno & $errorLevel;
	}

}